﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Drawing.Imaging;
using System.Web;

namespace NotesBook
{    
    public static class ClipboardHelper
    {
        public static bool IsBitmap
        {
            get { return Clipboard.GetDataObject().GetDataPresent(DataFormats.Bitmap); }
        }
        public static bool IsRtf
        {
            get { return Clipboard.GetDataObject().GetDataPresent(DataFormats.Rtf); }
        }
        public static bool IsHtml
        {
            get { return Clipboard.GetDataObject().GetDataPresent(DataFormats.Html); }
        }
        public static bool IsFileDrop
        {
            get { return Clipboard.GetDataObject().GetDataPresent(DataFormats.FileDrop); }
        }

        public static Bitmap Bitmap
        {
            get { return (Bitmap)Clipboard.GetDataObject().GetData(DataFormats.Bitmap); }
        }
        public static string Rtf
        {
            get { return (string)Clipboard.GetDataObject().GetData(DataFormats.Rtf); }
        }
        public static string Html
        {
            get
            {
                MemoryStream ms = Clipboard.GetData("Html Format") as MemoryStream;
                ms.Position = 0;
                byte[] vBytes = new byte[ms.Length];
                ms.Read(vBytes, 0, (int)ms.Length);
                string s = Encoding.UTF8.GetString(vBytes);

                string htmlContent = string.Empty;
                Regex regImg = new Regex(@"<!--StartFragment-->(\r\n)?([\s\S]*)(\r\n)?<!--EndFragment-->", RegexOptions.Multiline);
                Match match = regImg.Match(s);
                if (match.Success)
                    htmlContent = match.Groups[2].Value;
                return htmlContent;
            }
        }
        public static string[] FileDrop
        {
            get { return (string[])Clipboard.GetDataObject().GetData(DataFormats.FileDrop); }
        }
    }
    
    public static class HtmlHelper
    {

        #region 正则

        private static string regHtmlFilter = @"(<[a-z][^>]*\s)(?:id|name|class|on\w+|\w+:\w+)=(?:[""']?[^""']*[""']?|\w+)\s?";
        private static Regex regLocal = new Regex(@"^file:///", RegexOptions.IgnoreCase);
        private static Regex regWeb = new Regex(@"^(https?|ftp)://", RegexOptions.IgnoreCase);


        #endregion

        private static List<string> extensions = new List<string>(new string[] { ".tiff", ".gif", ".bmp", ".jpg", ".png", ".ico" });
        
        //粘贴过滤(id, name, class 等等)
        private static string FilterPasteHtml(string sHtmlText)
        {
            int len = sHtmlText.Length;
            sHtmlText = Regex.Replace(sHtmlText, regHtmlFilter, "$1", RegexOptions.IgnoreCase | RegexOptions.Multiline);
            while (len != sHtmlText.Length)
            {
                len = sHtmlText.Length;
                sHtmlText = Regex.Replace(sHtmlText, regHtmlFilter, "$1", RegexOptions.IgnoreCase | RegexOptions.Multiline);
            }
            return sHtmlText;
        }

        ////获取html中所有img标签中的src属性
        //public static string[] GetHtmlImageUrlList(string sHtmlText)
        //{
        //    //定义正则表达式用来匹配img标签   
        //    Regex regImg = new Regex(@"<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>", RegexOptions.IgnoreCase);
        //    //搜索匹配的字符串
        //    MatchCollection matches = regImg.Matches(sHtmlText);
        //    int i = 0;
        //    string[] sUrlList = new string[matches.Count];
        //    //取得匹配项列表   
        //    foreach (Match match in matches)
        //        sUrlList[i++] = match.Groups["imgUrl"].Value;
        //    return sUrlList;
        //}
       
        //Rtf转Html
        public static string Rtf2Html(string rtfString, string imgSavePath)
        {
            SautinSoft.RtfToHtml r = new SautinSoft.RtfToHtml();
            r.OutputFormat = SautinSoft.eOutputFormat.XHTML_10;
            r.Encoding = SautinSoft.eEncoding.UTF_8;
            r.ImageStyle.ImageFolder = Helper.GetParentDir(imgSavePath);
            r.ImageStyle.ImageSubFolder = Helper.GetSubFolder(imgSavePath);
            r.ImageStyle.ImageFileName = Helper.NewGuid();
            r.ImageStyle.IncludeImageInHtml = false;
            string regImg = @"(<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*)(?<imgUrl>[^\s\t\r\n""'<>]*)([^<>]*?/?[\s\t\r\n]*>)";

            return Regex.Replace(r.ConvertString(rtfString), regImg, new MatchEvaluator(delegate(Match m)
            {
                string imgName = Path.GetFileName(m.Groups[3].Value);
                string path = imgSavePath + imgName;
                string newPath = imgSavePath + Helper.NewGuid() + Path.GetExtension(path);
                File.Move(path, newPath);
                return string.Format(@"{0}file:///{1}{2}", m.Groups[1].Value, newPath, m.Groups[2].Value);
            }), RegexOptions.IgnoreCase | RegexOptions.Multiline);
        }

        //网页复制的html转本地
        public static string Web2Html(string htmlContent, string imgSavePath, DownloadPicDelegate downPicDelegate)
        {
            string regSrc = @"<img[\s\t\r\n]*([^<>]*?)[\s\t\r\n]*src[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*([^\t\r\n""'<>]*)[""']?([^<>]*?)/?[\s\t\r\n]*>";
            return Regex.Replace(FilterPasteHtml(htmlContent), regSrc, new MatchEvaluator(delegate(Match m)
            {
                string url = m.Groups[2].Value;//匹配的src里面的url
                string path = imgSavePath;
                //图片存在于本地磁盘
                if (regLocal.IsMatch(url))
                {
                    string filename = Regex.Replace(url, @"^file:///([^\t\r\n""'<>]*)", "$1", RegexOptions.IgnoreCase);
                    //图片存在于imgSavePath所在的目录
                    if (Path.GetDirectoryName(filename) == Path.GetDirectoryName(path))
                        path = filename;
                    else
                    {
                        path += (Helper.NewGuid() + Path.GetExtension(filename));
                        File.Copy(filename, path);
                    }
                }
                //图片来源于网上
                else if (regWeb.IsMatch(url))
                    path = Helper.DownLoadFile(url, path, downPicDelegate);
                else
                    throw new System.ArgumentException("未知的url协议.");

                //如果没有后缀或者不是图片后缀, 就修正后缀
                //if (string.IsNullOrEmpty(Path.GetExtension(path)) || !extensions.Contains(Path.GetExtension(path).ToLower()))
                //{
                //    string oldPath = path;
                //    path += ImageHelper.JudgeImageExtension(path);
                //    File.Move(oldPath, path);
                //}

                return string.Format("<img {0} src=\"file:///{1}\" {2} />", m.Groups[1].Value, path, m.Groups[3].Value);
            }), RegexOptions.IgnoreCase | RegexOptions.Multiline);
        }

        //bitmap转Html
        public static string Bitmap2Html(Bitmap b, string imgSavePath)
        {
            string path = imgSavePath + Helper.NewGuid() + ".png";
            b.Save(path);
            return string.Format(@"<img src='file:///{0}' />", path);
        }

        //附件转html
        public static string Attach2Html(string[] files, string imgSavePath, string fileSavePath, InsertAttachDelegate insertAttDelegate)
        {
            string html = string.Empty;
            for (int i = 0; i < files.Length; i++)
            {
                if (File.Exists(files[i]))
                {
                    string guid = Helper.NewGuid();
                    string extension = Path.GetExtension(files[i]).ToLower();
                    //是图片就直接贴图片
                    if ((extension == ".jpg" || extension == ".png" || extension == ".bmp" || extension == ".gif") && ImageHelper.IsRealImage(files[i]))
                    {
                        string path = imgSavePath + guid + extension;
                        File.Copy(files[i], path, false);
                        html += string.Format("<img src=\"file:///{0}\" />", path);
                    }
                    else//不是图片就贴附件
                    {
                        if (insertAttDelegate != null)
                            insertAttDelegate(new InsertAttachArgs(files[i], guid));
                        html += string.Format(@"<img src='data:image/x-png;base64,{0}' attach='{1}'/>", ImageHelper.ImageToBase64(ImageHelper.DrawAttachImg(files[i]), ImageFormat.Png), guid);
                    }
                }
            }
            return html;
        }
    }

    public class ImageHelper
    {
        #region 获取文件类型图标
        
        private enum SHGFI
        {
            SHGFI_ICON = 0x000000100,           //   get   icon 
            SHGFI_DISPLAYNAME = 0x000000200,           //   get   display   name 
            SHGFI_TYPENAME = 0x000000400,           //   get   type   name 
            SHGFI_ATTRIBUTES = 0x000000800,           //   get   attributes 
            SHGFI_ICONLOCATION = 0x000001000,           //   get   icon   location 
            SHGFI_EXETYPE = 0x000002000,           //   return   exe   type 
            SHGFI_SYSICONINDEX = 0x000004000,           //   get   system   icon   index 
            SHGFI_LINKOVERLAY = 0x000008000,           //   put   a   link   overlay   on   icon 
            SHGFI_SELECTED = 0x000010000,           //   show   icon   in   selected   state 
            SHGFI_ATTR_SPECIFIED = 0x000020000,           //   get   only   specified   attributes 
            SHGFI_LARGEICON = 0x000000000,           //   get   large   icon 
            SHGFI_SMALLICON = 0x000000001,           //   get   small   icon 
            SHGFI_OPENICON = 0x000000002,           //   get   open   icon 
            SHGFI_SHELLICONSIZE = 0x000000004,           //   get   shell   size   icon 
            SHGFI_PIDL = 0x000000008,           //   pszPath   is   a   pidl 
            SHGFI_USEFILEATTRIBUTES = 0x000000010           //   use   passed   dwFileAttribute 
        }

        private struct SHFILEINFO
        {
            public SHFILEINFO(bool b)
            {
                hIcon = IntPtr.Zero; iIcon = 0; dwAttributes = 0; szDisplayName = ""; szTypeName = "";
            }
            public IntPtr hIcon;
            public int iIcon;
            public uint dwAttributes;
            [MarshalAs(UnmanagedType.LPStr, SizeConst = 260)]
            public string szDisplayName;
            [MarshalAs(UnmanagedType.LPStr, SizeConst = 80)]
            public string szTypeName;
        };

        [DllImport("Shell32.dll")]
        private static extern IntPtr SHGetFileInfo
        (
                string pszPath,
                uint dwFileAttributes,
                out SHFILEINFO psfi,
                uint cbfileInfo,
                SHGFI uFlags
        );
        //取文件关联图标 
        public static Icon GetIcon(string strPath, bool bSmall)
        {
            SHFILEINFO info = new SHFILEINFO(true);
            int cbFileInfo = Marshal.SizeOf(info);
            SHGFI flags;
            if (bSmall)
                flags = SHGFI.SHGFI_ICON | SHGFI.SHGFI_SMALLICON;//16*16小图标 
            else
                flags = SHGFI.SHGFI_ICON | SHGFI.SHGFI_LARGEICON;//32*32大图标 

            SHGetFileInfo(strPath, 256, out info, (uint)cbFileInfo, flags);

            return Icon.FromHandle(info.hIcon);
        }

        #endregion

        #region 绘图

        //画圆角矩形
        public static void DrawRoundedRectangle(Graphics g, Color c, int x, int y, int width, int height, int r)
        {
            //创建一个红色的画笔
            Pen pen = new Pen(c);
            //画矩形上面的边
            g.DrawLine(pen, x + r, y, x + width - r, y);
            //画矩形下面的边
            g.DrawLine(pen, x + r, y + height, x + width - r, y + height);
            //画矩形左面的边
            g.DrawLine(pen, x, y + r, x, y + height - r);
            //画矩形右面的边
            g.DrawLine(pen, x + width, y + r, x + width, y + height - r);
            //画矩形左上角的圆角
            g.DrawArc(pen, x, y, 2 * r, 2 * r, 180, 90);
            //画矩形右下角的圆角
            g.DrawArc(pen, x + width - 2 * r, y + height - 2 * r, 2 * r, 2 * r, 360, 90);
            //画矩形右上角的圆角
            g.DrawArc(pen, x + width - 2 * r, y, 2 * r, 2 * r, 270, 90);
            //画矩形左下角的圆角
            g.DrawArc(pen, x, y + height - 2 * r, 2 * r, 2 * r, 90, 90);
        }

        //填充圆角矩形
        public static void FillRoundedRectangle(Graphics g, Color c, int x, int y, int width, int height, int r)
        {
            //创建画刷
            Brush brush = new SolidBrush(c);
            if (r == 0)
            {
                g.FillRectangle(brush, x, y, width, height);
            }
            else
            {
                GraphicsPath path = new GraphicsPath();
                path.AddArc(x, y, r * 2, r * 2, 180, 90);
                path.AddArc(x + width - r * 2, y, r * 2, r * 2, 270, 90);
                path.AddArc(x + width - r * 2, y + height - r * 2, r * 2, r * 2, 0, 90);
                path.AddArc(x, y + height - r * 2, r * 2, r * 2, 90, 90);
                path.CloseFigure();
                g.FillPath(brush, path);
            }
        }

        #endregion

        #region 生成代表附件的图片

        public static Bitmap DrawAttachImg(string file)
        {
            string shortName = Path.GetFileName(file);
            string s2 = string.Format("{0:yyyy-MM-dd HH:mm}, {1}", DateTime.Now, Helper.FormatFileSize(new FileInfo(file).Length));
            int strLen = Math.Max(Encoding.Default.GetBytes(shortName).Length, s2.Length);
            int rgb = 230, x = 6, y = 6, width = 45 + strLen * 7, height = 50;

            Bitmap b = new Bitmap(width + 7, height + 7);
            Graphics g = Graphics.FromImage(b);
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;
            g.Clear(Color.White);   //清空背景色
            //画阴影
            for (int j = 0; j < 6; j++)
            {
                FillRoundedRectangle(g, Color.FromArgb(rgb, rgb, rgb), x, y, width, height, 5);
                x--;
                y--;
                rgb -= 15;
            }
            //画正文区域
            FillRoundedRectangle(g, Color.White, x + 2, y + 2, width - 2, height - 2, 5);
            //画图标
            g.DrawIcon(GetIcon(file, false), x + 8, y + 9);
            //画文件名
            g.DrawString(shortName, new Font("Arial", 10, FontStyle.Regular), new SolidBrush(Color.FromArgb(60, 77, 129)), x + 45, y + 9);
            //画时间和文件大小
            g.DrawString(s2, new Font("Arial", 10, FontStyle.Regular), new SolidBrush(Color.FromArgb(60, 77, 129)), x + 45, y + 25);
            return b;
        }

        #endregion

        #region Base64和图片互转

        /// <summary>
        /// 图像转换为Base64编码
        /// </summary>
        /// <param name="image">图像</param>
        /// <param name="format">图像格式</param>
        /// <returns>转换成功返回其Base64编码；失败返回空串</returns>
        public static string ImageToBase64(Image image)
        {
            string base64String = "";
            using (MemoryStream ms = new MemoryStream())
            {
                image.Save(ms, JudgeImageFormat(image));
                byte[] imageBytes = ms.ToArray();
                base64String = Convert.ToBase64String(imageBytes);
            }
            return base64String;
        }
        public static string ImageToBase64(Image image, ImageFormat format)
        {
            string base64String = "";
            using (MemoryStream ms = new MemoryStream())
            {
                image.Save(ms, format);
                byte[] imageBytes = ms.ToArray();
                base64String = Convert.ToBase64String(imageBytes);
            }
            return base64String;
        }

        /// <summary>
        /// Base64编码转换为图像
        /// </summary>
        /// <param name="base64String">Base64字符串</param>
        /// <returns>转换成功返回图像；失败返回null</returns>
        public static Image Base64ToImage(string base64String)
        {
            MemoryStream ms = null;
            Image image = null;
            try
            {
                byte[] imageBytes = Convert.FromBase64String(base64String);
                ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
                ms.Write(imageBytes, 0, imageBytes.Length);
                image = Image.FromStream(ms, true);
            }
            catch
            {
            }
            finally
            {
                if (ms != null) ms.Close();
            }
            return image;
        }

        #endregion

        #region 判断图片类型
        public static ImageFormat JudgeImageFormat(Image image)
        {
            ImageFormat FormetType = ImageFormat.Jpeg;
            if (image.RawFormat.Guid == ImageFormat.Tiff.Guid)
                FormetType = ImageFormat.Tiff;
            else if (image.RawFormat.Guid == ImageFormat.Gif.Guid)
                FormetType = ImageFormat.Gif;
            else if (image.RawFormat.Guid == ImageFormat.Jpeg.Guid)
                FormetType = ImageFormat.Jpeg;
            else if (image.RawFormat.Guid == ImageFormat.Bmp.Guid)
                FormetType = ImageFormat.Bmp;
            else if (image.RawFormat.Guid == ImageFormat.Png.Guid)
                FormetType = ImageFormat.Png;
            else if (image.RawFormat.Guid == ImageFormat.Icon.Guid)
                FormetType = ImageFormat.Icon;
            else
                throw new System.ArgumentException("未知的图片格式.");
            return FormetType;
        }
        public static ImageFormat JudgeImageFormat(string imagePath)
        {
            Image img = Image.FromFile(imagePath);
            ImageFormat format = JudgeImageFormat(img);
            img.Dispose();
            return format;
        }
        #endregion

        #region 判断图片后缀
        public static string JudgeImageExtension(Image image)
        {
            string extention = string.Empty;
            if (image.RawFormat.Guid == ImageFormat.Tiff.Guid)
                extention = ".tiff";
            else if (image.RawFormat.Guid == ImageFormat.Gif.Guid)
                extention = ".gif";
            else if (image.RawFormat.Guid == ImageFormat.Jpeg.Guid)
                extention = ".jpg";
            else if (image.RawFormat.Guid == ImageFormat.Bmp.Guid)
                extention = ".bmp";
            else if (image.RawFormat.Guid == ImageFormat.Png.Guid)
                extention = ".png";
            else if (image.RawFormat.Guid == ImageFormat.Icon.Guid)
                extention = ".ico";
            else
                throw new System.ArgumentException("未知的图片格式.");
            return extention;
        }
        public static string JudgeImageExtension(string imagePath)
        {
            Image img = Image.FromFile(imagePath);
            string extension = JudgeImageExtension(img);
            img.Dispose();
            return extension;
        }
        #endregion

        #region 根据文件路径判断该文件是否为(jpg:255216;gif:7173;BMP:6677,PNG:13780)

        public static bool IsRealImage(string file)
        {
            using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                using (BinaryReader r = new BinaryReader(fs))
                {
                    string fileclass = "";
                    byte buffer;
                    buffer = r.ReadByte();
                    fileclass = buffer.ToString();
                    buffer = r.ReadByte();
                    fileclass += buffer.ToString();
                    if (fileclass == "255216" || fileclass == "7173" || fileclass == "6677" || fileclass == "13780")
                        return true;
                    else
                        return false;
                }
            }
        }

        #endregion
    }

    public static class Helper
    {
        private static string pattern = @"^([a-z]:[/\\]([\s\S]+[/\\])*)([\s\S]+)[/\\]?$";

        //格式化文件大小
        public static string FormatFileSize(long size)
        {
            string strSize = string.Empty;
            if (size < 1024)
            {
                strSize = string.Format("{0:N2}", size) + " B";
            }
            else if (size > 1024 && size < 1024 * 1024)
            {
                size /= 1024;
                strSize = string.Format("{0:N2}", size) + " KB";
            }
            else if (size > 1024 * 1024)
            {
                size /= 1024 * 1024;
                strSize = string.Format("{0:N2}", size) + " MB";
            }
            return strSize;
        }

        //获取唯一字符串
        public static string NewGuid()
        {
            long i = 1;
            foreach (byte b in Guid.NewGuid().ToByteArray())
            {
                i *= ((int)b + 1);
            }
            return string.Format("{0:x}", i - DateTime.Now.Ticks);
        }

        //获取父路径
        public static string GetParentDir(string path)
        {
            Match match = Regex.Match(path, pattern, RegexOptions.IgnoreCase);
            if (match.Success)
                return match.Groups[1].Value;
            else
                return string.Empty;
        }

        //获取路径的最后一级文件夹
        public static string GetSubFolder(string path)
        {            
            Match match = Regex.Match(path, pattern, RegexOptions.IgnoreCase);
            if (match.Success)
                return match.Groups[3].Value;
            else
                return string.Empty;
        }

        //下载文件(进度条显示)
        public static string DownLoadFile(string URL, string fileSavePath, DownloadPicDelegate downPicDelegate)
        {
            //URL = HttpUtility.HtmlDecode(URL);
            System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); //从URL地址得到一个WEB请求
            Myrq.Proxy = null;
            Myrq.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)";
            Myrq.ContentType = "application/x-www-form-urlencoded";
            Myrq.Method = "GET";
            System.Net.WebResponse myrp = (System.Net.WebResponse)Myrq.GetResponse(); //从WEB请求得到WEB响应
            long totalBytes = myrp.ContentLength; //从WEB响应得到总字节数
            System.IO.Stream st = myrp.GetResponseStream(); //从WEB请求创建流（读）

            string extention = string.Empty;
            if (URL.LastIndexOf(".") != -1)
            {
                extention = URL.Substring(URL.LastIndexOf("."));
                if (extention.Length > 5)
                    extention = string.Empty;
            }
            fileSavePath += (Helper.NewGuid() + extention);
            Stream so = new FileStream(fileSavePath, FileMode.Create); //创建文件流（写）
            long totalDownloadedByte = 0; //下载文件大小
            byte[] by = new byte[2048];
            int osize = st.Read(by, 0, (int)by.Length); //读流
            while (osize > 0)
            {
                totalDownloadedByte = osize + totalDownloadedByte; //更新文件大小
                Application.DoEvents();
                so.Write(by, 0, osize); //写流
                if (downPicDelegate != null)
                {
                    DownloadPicArgs args = new DownloadPicArgs((int)((float)(totalDownloadedByte * 100) / (float)totalBytes));
                    downPicDelegate(args);
                }
                osize = st.Read(by, 0, (int)by.Length); //读流
            }
            so.Close(); //关闭流
            st.Close(); //关闭流
            if (downPicDelegate != null)
                downPicDelegate(new DownloadPicArgs(0));
            return fileSavePath;
        }
    }
}
